<?php

namespace Ignus\View\NodeVisitor;

use Ignus\View\Environment;
use Ignus\View\Node;
use Ignus\View\Node\Module;
use Ignus\View\Node\PrintNode;
use Ignus\View\Node\SandboxedPrint;
use Ignus\View\Node\SandboxedModule;
use Ignus\View\NodeInterface;
use Ignus\View\NodeVisitorInterface;
use Ignus\View\Node\Expression\Filter;
use Ignus\View\Node\Expression\FunctionExpr;

class Sandbox implements NodeVisitorInterface
{
    protected $inAModule = false;
    protected $tags;
    protected $filters;
    protected $functions;

    public function enterNode(NodeInterface $node, Environment $env)
    {
        if ($node instanceof Module) {
            $this->inAModule = true;
            $this->tags = array();
            $this->filters = array();
            $this->functions = array();

            return $node;
        }
        elseif ($this->inAModule) {
            // look for tags
            if ($node->getNodeTag()) {
                $this->tags[] = $node->getNodeTag();
            }

            // look for filters
            if ($node instanceof Filter) {
                $this->filters[] = $node->getNode('filter')->getAttribute('value');
            }

            // look for functions
            if ($node instanceof FunctionExpr) {
                $this->functions[] = $node->getAttribute('name');
            }

            // wrap print to check __toString() calls
            if ($node instanceof PrintNode) {
                return new SandboxedPrint($node->getNode('expr'), $node->getLine(), $node->getNodeTag());
            }
        }

        return $node;
    }

    public function leaveNode(NodeInterface $node, Environment $env)
    {
        if ($node instanceof Module) {
            $this->inAModule = false;

            return new SandboxedModule($node, array_unique($this->filters), array_unique($this->tags), array_unique($this->functions));
        }

        return $node;
    }

    public function getPriority()
    {
        return 0;
    }
}
